package com.idlecode.config;

import cn.hutool.core.util.StrUtil;
import com.idlecode.bean.DataSourceEntity;
import com.idlecode.config.query.*;
import com.idlecode.util.DbUtil;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 代码生成器 数据源
 */
public class GenDataSource {
    /**
     * 数据源ID
     */
    private String dsId;
    /**
     * 数据库类型
     */
    private DbType dbType;
    /**
     * 数据库URL
     */
    private String connUrl;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;

    private AbstractQuery dbQuery;

    private Connection connection;

    public GenDataSource(DataSourceEntity entity) {
        this.dsId = entity.getDsId();
        this.dbType = DbType.getValue(entity.getDbType());
        this.connUrl = entity.getConnUrl();
        this.username = entity.getUsername();
        this.password = entity.getPassword();

        if (dbType == DbType.MySQL) {
            this.dbQuery = new MySqlQuery();
        } else if (dbType == DbType.MariaDb) {
            this.dbQuery = new MariaDbQuery();
        } else if (dbType == DbType.Oracle) {
            this.dbQuery = new OracleQuery();
        } else if (dbType == DbType.PostgreSQL) {
            this.dbQuery = new PostgreSqlQuery();
        } else if (dbType == DbType.SQLServer) {
            this.dbQuery = new SQLServerQuery();
        } else if (dbType == DbType.DM) {
            this.dbQuery = new DmQuery();
        } else if (dbType == DbType.Clickhouse) {
            this.dbQuery = new ClickHouseQuery();
        }

        try {
            this.connection = DbUtil.getConnection(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public GenDataSource(DataSourceEntity entity, String dataBaseName) {
        this.dsId = entity.getDsId();
        this.dbType = DbType.getValue(entity.getDbType());
        this.connUrl = entity.getConnUrl();
        this.username = entity.getUsername();
        this.password = entity.getPassword();

        if (dbType == DbType.MySQL) {
            this.dbQuery = new MySqlQuery();
        } else if (dbType == DbType.MariaDb) {
            this.dbQuery = new MariaDbQuery();
        } else if (dbType == DbType.Oracle) {
            this.dbQuery = new OracleQuery();
        } else if (dbType == DbType.PostgreSQL) {
            if (StrUtil.isNotBlank(dataBaseName) && !"null".equals(dataBaseName)) {
                this.connUrl = replaceDatabaseName(entity.getConnUrl(), dataBaseName);
            }
            this.dbQuery = new PostgreSqlQuery();
        } else if (dbType == DbType.SQLServer) {
            this.dbQuery = new SQLServerQuery();
        } else if (dbType == DbType.DM) {
            this.dbQuery = new DmQuery();
        } else if (dbType == DbType.Clickhouse) {
            this.dbQuery = new ClickHouseQuery();
        }

        try {
            this.connection = DbUtil.getConnection(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public GenDataSource(Connection connection) throws SQLException {
        this.dbType = DbType.getValue(connection.getMetaData().getDatabaseProductName());

        if (dbType == DbType.MySQL) {
            this.dbQuery = new MySqlQuery();
        } else if (dbType == DbType.MariaDb) {
            this.dbQuery = new MariaDbQuery();
        } else if (dbType == DbType.Oracle) {
            this.dbQuery = new OracleQuery();
        } else if (dbType == DbType.PostgreSQL) {
            this.dbQuery = new PostgreSqlQuery();
        } else if (dbType == DbType.SQLServer) {
            this.dbQuery = new SQLServerQuery();
        } else if (dbType == DbType.DM) {
            this.dbQuery = new DmQuery();
        } else if (dbType == DbType.Clickhouse) {
            this.dbQuery = new ClickHouseQuery();
        }

        this.connection = connection;
    }

    /**
     * 替换数据库名称
     */
    private static String replaceDatabaseName(String jdbcUrl, String dataBaseName) {
        // 从 JDBC 连接字符串中提取数据库名称
        String[] parts = jdbcUrl.split("\\?");
        String mainPart = parts[0]; // 获取连接字符串的主要部分

        // 根据主要部分提取数据库名称
        String[] subParts = mainPart.split("/");
        String dbName = subParts[subParts.length - 1];

        try {
            // 解码数据库名称（如果包含特殊字符）
            dbName = URLDecoder.decode(dbName, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return jdbcUrl.replace("/" + dbName, "/" + dataBaseName);
    }

    public String getDsId() {
        return dsId;
    }

    public void setDsId(String dsId) {
        this.dsId = dsId;
    }

    public DbType getDbType() {
        return dbType;
    }

    public void setDbType(DbType dbType) {
        this.dbType = dbType;
    }

    public String getConnUrl() {
        return connUrl;
    }

    public void setConnUrl(String connUrl) {
        this.connUrl = connUrl;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public AbstractQuery getDbQuery() {
        return dbQuery;
    }

    public void setDbQuery(AbstractQuery dbQuery) {
        this.dbQuery = dbQuery;
    }

    public Connection getConnection() {
        return connection;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    @Override
    public String toString() {
        return "GenDataSource{" +
                "dsId='" + dsId + '\'' +
                ", dbType=" + dbType +
                ", connUrl='" + connUrl + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", dbQuery=" + dbQuery +
                ", connection=" + connection +
                '}';
    }
}
